package keyfun.mobile.utils
{
    import flash.display.BitmapData;
    import flash.display.Loader;
	import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.MediaEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
	import flash.geom.Matrix;
    import flash.media.CameraRoll;
    import flash.media.CameraUI;
    import flash.media.MediaPromise;
    import flash.media.MediaType;
    import flash.utils.ByteArray;
	import flash.events.IOErrorEvent;
	import flash.events.ErrorEvent;
	import flash.utils.IDataInput;
	import flash.display.Bitmap;
	import keyfun.mobile.images.JPEGEncoder;
	import flash.display.JPEGEncoderOptions;
	
	import com.leeburrows.utilities.encoders.ThreadedJPEGencoder;
	import com.leeburrows.utilities.encoders.ThreadedPNGencoder;
	import com.leeburrows.utilities.encoders.events.ThreadedEncoderEvent;
	import com.leeburrows.utilities.encoders.interfaces.IThreadedImageEncoder;

    public class CameraUtil extends Sprite
    {
		private var mediaPromise:MediaPromise;
		private var dataSource:IDataInput;
        private var cameraUI:CameraUI;
        private var imageLoader:Loader;
        public var file:File;
		private var _onFileReady:Function;
		public var resizedBitmap:Bitmap;
		private var encoder:IThreadedImageEncoder;

        public function CameraUtil(onFileReady:Function = null)
        {
            if (CameraUI.isSupported)
            {
				_onFileReady = onFileReady;
                cameraUI = new CameraUI();
                cameraUI.addEventListener(MediaEvent.COMPLETE, mediaEventComplete);
				cameraUI.addEventListener(Event.CANCEL, captureCanceled); 
				cameraUI.addEventListener(ErrorEvent.ERROR, cameraError);
				cameraUI.launch(MediaType.IMAGE);
            }
        }

        private function mediaEventComplete(event:MediaEvent):void
        {
			trace("mediaEventComplete");
            mediaPromise = event.data;
			dataSource = mediaPromise.open();
			
            if (mediaPromise.file == null)
            {
				trace("mediaEventComplete:ios");
                // For iOS we need to load with a Loader first
                imageLoader = new Loader();
                imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleted);
				imageLoader.addEventListener(IOErrorEvent.IO_ERROR, cameraError);
                imageLoader.loadFilePromise(mediaPromise);
				trace("mediaEventComplete:ios-end");
            }
            else
            {
				trace("mediaEventComplete:android");
                // Android we can just dispatch the event that it's complete
                file = new File(mediaPromise.file.url);
                if (_onFileReady != null)
				{
					_onFileReady();
				}
            }
        }
		
		private function captureCanceled(event:Event):void
		{
			trace("Image captureCanceled.");
		}
		
		private function cameraError(event:IOErrorEvent):void
		{
			trace("Image cameraError.");
		}
		
        private function loaderCompleted(event:Event):void
        {
			trace("loaderCompleted");
            imageLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderCompleted);
            imageLoader.removeEventListener(IOErrorEvent.IO_ERROR, cameraError);
			
            var bitmapData:BitmapData = Bitmap(imageLoader.content).bitmapData;
			var bitmap:Bitmap = new Bitmap(bitmapData, "auto", true);
			trace("aaa:" + bitmap.width, bitmap.height);
			
			var isPortrait:Boolean = (bitmapData.height / bitmapData.width) > 1.0;
			var forRatio:int = Math.min(AppGlobal.mainStage.fullScreenHeight, AppGlobal.mainStage.fullScreenWidth);

			var ratio:Number;
			if (isPortrait) 
			{
				ratio = forRatio / bitmapData.width;
			} 
			else 
			{
				ratio = forRatio / bitmapData.height;
			}
			bitmap.width = bitmapData.width * ratio;
			bitmap.height = bitmapData.height * ratio;
			
			trace("bbb:" + bitmap.width, bitmap.height);

			var m:Matrix = new Matrix();
			if (!isPortrait) 
			{
				bitmap.x = AppGlobal.mainStage.fullScreenWidth;
				bitmap.rotation = 90;
			
				m.rotate(90 * Math.PI / 180);
				m.scale(ratio, ratio);
				m.translate(AppGlobal.mainStage.stageWidth, 0);
			}
			
			trace("ccc:" + bitmap.width, bitmap.height);
			
			var resizedBmd:BitmapData = new BitmapData(bitmap.width, bitmap.height);
			resizedBmd.draw(bitmap, m);
			resizedBitmap = new Bitmap(resizedBmd);
			trace("rrr:" + resizedBitmap.width, resizedBitmap.height);
			
			addToCameraRoll(resizedBmd);
			
			//buildEncoder();
			//encoder.encode(resizedBmd, 60);
	
			file = File.documentsDirectory.resolvePath("receipt" + new Date().time + ".jpg");
			
			var stream:FileStream = new FileStream()
			stream.open(file, FileMode.WRITE);
			var bytes:ByteArray = resizedBmd.encode(resizedBmd.rect, new JPEGEncoderOptions());
			stream.writeBytes(bytes, 0, bytes.bytesAvailable);
			stream.close();
			
			trace(file.url);
			
			if (_onFileReady != null)
			{
				_onFileReady();
			}
        }
		
		public function addToCameraRoll(bmd:BitmapData):void
		{
			if (CameraRoll.supportsAddBitmapData)
			{
				var cameraRoll:CameraRoll = new CameraRoll();
				cameraRoll.addBitmapData(bmd);
				cameraRoll = null;
			}
		}
		
		private function buildEncoder():void
		{
			//use this line to encode as a JPG, argument defines quality (1-100)
			encoder = new ThreadedJPEGencoder(80);
			//use this line to encode as a PNG
			//encoder = new ThreadedPNGencoder();
			//add encoder listeners
			encoder.addEventListener(ThreadedEncoderEvent.PROGRESS, encodingHandler);
			encoder.addEventListener(ThreadedEncoderEvent.COMPLETED, encodingHandler);
		}
		
		private function encodingHandler(event:ThreadedEncoderEvent):void
		{
			trace("encodingHandler:" + event.ratioComplete);
			if (event.type == ThreadedEncoderEvent.COMPLETED)
			{
				file = File.documentsDirectory.resolvePath("receipt" + new Date().time + ".jpg");
				var stream:FileStream = new FileStream();
				stream.open(file, FileMode.WRITE);
				stream.writeBytes(encoder.data, 0, encoder.data.length);
				trace(file.url);
				
				if (_onFileReady != null)
				{
					_onFileReady();
				}
			}
		}

    }
}